#include "PersistentFoodList.h"

ostream& operator<<(ostream& stream, FoodName foodname)
{
	stream << foodname.id << " " << foodname.groupID << " " << foodname.abbrFoodnameE << " "
			<< foodname.abbrFoodnameF << " " << foodname.foodnameE << " " << foodname.foodnameF << endl;
	return stream;
}

ostream& operator<<(ostream& stream, FoodGroupName fgn)
{
	stream << fgn.id << " " << fgn.groupnameE << " " << fgn.groupnameF << endl;
	return stream;
}

PersistentFoodList::PersistentFoodList()
{
	read();
}

PersistentFoodList::~PersistentFoodList()
{
}

void PersistentFoodList::read()
{
	fstream foodnameFile("foods/cnf/FOOD_NM.txt", std::ios::in);

	if(!foodnameFile || foodnameFile.fail()) {
		cerr << "Failed to open file FOOD_NM.txt" << endl;
		return;
	}

	map<int, FoodName> names;
	map<int, FoodGroupName> groupnames;
	map<int, map<int, NutritionAmount> > nutritionAmounts;
	map<int, NutritionName> nutritionNames;
	map<int, Measure> measures;
	map<int, ConversionFactor> factors;

	string line;

	int i = 0;
	bool stop = false;
	getline(foodnameFile, line);
	string empty;
	while (getline(foodnameFile, line) && !stop) {
		stringstream ss(line);
		//		FoodName foodname;
		//		ss >> foodname.id;
		//		ss >> foodname.groupID;
		//		ss >> empty;
		//		ss >> empty;
		//		ss >> foodname.foodnameE;
		//		ss >> foodname.foodnameF;
		//
		//		names[foodname.id] = foodname;
		vector<string> items;
		items.reserve(7);
		string item;
		int j = 0;
		while (getline(ss, item, '$') && j++ < 7) {
			items.push_back(item);
		}
		if(items.size() > 6) {
			int id = atoi(items[0].c_str());
			int gid = atoi(items[1].c_str());
			if(id >= 0 && gid >= 0) {
				FoodName foodname(id, gid, items[3], items[4], items[5], items[6]);
				names[foodname.id] = foodname;
			}
		}

		if(i++ > 9000)
			stop = true;
	}

	fstream foodGroupFile("foods/cnf/FOOD_GRP.txt", std::ios::in);

	getline(foodGroupFile, line); //absorb header line

	while (getline(foodGroupFile, line)) {
		stringstream ss(line);
		//		FoodGroupName groupname;
		//		ss >> groupname.id;
		//		ss >> empty;
		//		ss >> groupname.groupnameE;
		//		ss >> groupname.groupnameF;
		vector<string> items;
		items.reserve(4);
		string item;
		while (getline(ss, item, '$')) {
			items.push_back(item);
		}
		if(items.size() > 3) {
			FoodGroupName groupname(atoi(items[0].c_str()), items[2], items[3]);
			groupnames[groupname.id] = groupname;
		}
	}

	fstream nutrValueFile("foods/cnf/NT_AMT.txt", std::ios::in);

	i = 0;
	stop = false;
	getline(nutrValueFile, line);
	while (getline(nutrValueFile, line) && !stop) {
		stringstream ss(line);
		NutritionAmount na;
		string item;
		getline(ss, item, '$');
		na.foodID = atoi(item.c_str());
		getline(ss, item, '$');
		na.ntID = atoi(item.c_str());
		getline(ss, item, '$');
		na.amount = atof(item.c_str());

		nutritionAmounts[na.foodID][na.ntID] = na;
	}

	fstream nutrNameFile("foods/cnf/NT_NM.txt", std::ios::in);

	getline(nutrNameFile, line);
	while (getline(nutrNameFile, line)) {
		stringstream ss(line);
		vector<string> items;
		items.reserve(10);
		string item;
		while (getline(ss, item, '$')) {
			items.push_back(item);
		}
		NutritionName nn(atoi(items[0].c_str()), items[2], items[3], items[4], items[5]);
		nutritionNames[nn.id] = nn;
	}

	fstream servingSizeFile("foods/cnf/MEASURE.txt", std::ios::in);

	getline(servingSizeFile, line);
	while (getline(servingSizeFile, line)) {
		stringstream ss(line);
		vector<string> items;
		items.reserve(5);
		string item;
		while (getline(ss, item, '$')) {
			items.push_back(item);
		}
		if(items.size() > 1) {
			Measure m(atoi(items[0].c_str()), String(items[1].c_str()));
			measures[m.id] = m;
		}
	}

	fstream conversionFactorFile("foods/cnf/CONV_FAC.txt", std::ios::in);

	getline(conversionFactorFile, line);
	while (getline(conversionFactorFile, line)) {
		stringstream ss(line);
		vector<string> items;
		string item;
		items.reserve(3);
		int j = 0;
		while (getline(ss, item, '$') && j++ < 3) {
			items.push_back(item);
		}
		if(items.size() > 2) {
			ConversionFactor factor(atoi(items[0].c_str()), atoi(items[1].c_str()), atof(items[2].c_str()));
			factors[factor.fid] = factor;
		}
	}

	//	for(map<int, map<int, NutritionAmount> >::const_iterator nit = nutritionAmounts.begin(); nit != nutritionAmounts.end(); ++nit) {
	//		for(map<int, NutritionAmount>::const_iterator mit = nit->second.begin(); mit != nit->second.end(); ++mit) {
	//			cout << mit->second.foodID << " " << mit->second.ntID << " " << mit->second.amount << endl;
	//		}
	//	}

	//	for (map<int, NutritionName>::const_iterator nit = nutritionNames.begin(); nit
	//			!= nutritionNames.end(); ++nit) {
	//		cout << nit->second.id << " " << nit->second.nameE << " " << nit->second.unit << endl;
	//	}

	for(map<int, FoodName>::const_iterator mit = names.begin(); mit != names.end(); ++mit) {
		NutritionalInfo info;
		map<int, NutritionAmount>& na = nutritionAmounts[mit->first];

		info.totalFat = na[204].amount;
		info.saturatedFat = na[606].amount;
		info.transFat = na[605].amount;
		info.cholesterol = na[601].amount;
		info.sodium = na[307].amount;
		info.totalCarb = na[205].amount;
		info.fibre = na[291].amount;
		info.sugar = na[269].amount;
		info.protein = na[203].amount;
		info.alcohol = na[221].amount;
		info.vitaminC = na[401].amount;
		info.vitaminD = na[339].amount;
		info.calcium = na[301].amount;
		info.iron = na[303].amount;
		info.calories = na[208].amount;
		info.caffeine = na[262].amount;
		info.potassium = na[306].amount;
		info.vitaminA = na[319].amount + na[321].amount * 0.1666f;

		Eatable food;
		food.id = mit->first;
		food.setName(mit->second.foodnameE);
		int gid = mit->second.groupID - 1;
		if(gid == 24)
			gid = 22;
		food.servingDesc = measures[factors[mit->first].mid].desc;
		food.servingFactor = factors[mit->first].factor;
		food.setImage(gid);
		food.gid = gid;
		food.setInfo(info);
		foods.push_back(food);

		//		for (map<int, NutritionName>::const_iterator nit = nutritionNames.begin(); nit
		//				!= nutritionNames.end(); ++nit) {
		//			float amount = nutritionAmounts[mit->second.id][nit->second.id].amount;
		////			Food food;
		//			if (amount > 0)
		//				cout << amount << " " << nit->second.unit << " " << nit->second.nameE << endl;
		//		}
		//		cout << endl;
	}

	sort(foods.begin(), foods.end());

	// those "/3/200" items are at the front now,
	//don't know how they got there but I'm just
	//hacking them off
	foods.pop_front();
	foods.pop_front();

	for(deque<Eatable>::iterator eit = foods.begin(); eit != foods.end(); ++eit) {
		foodMap[eit->id] = &(*eit);
	}

	NutritionalInfo info;
	meals.push_back(Eatable(T("Almond Cookies"), T("images/meals/AlmondCookies.jpg"), info));
	meals.push_back(Eatable(T("Fettucini"), T("images/meals/fettuciniShrimp.jpg"), info));
	meals.push_back(Eatable(T("Broccoli Soup"), T("images/meals/BroccoliSoup.jpg"), info));
	meals.push_back(Eatable(T("Reuben's Rolls"), T("images/meals/ReubensRolls.jpg"), info));
	meals.push_back(Eatable(T("Shrimp Creole"), T("images/meals/ShrimpCreole.jpg"), info));
	meals.push_back(Eatable(T("Chili Con Carne"), T("images/meals/chiliconcarne.jpg"), info));
	meals.push_back(Eatable(T("Sesame Garlic Steak"), T("images/meals/SesameGarlicSteak.jpg"), info));
	meals.push_back(Eatable(T("Apple - Grape Salad"), T("images/meals/AppleGrapeSalad.jpg"), info));
	meals.push_back(Eatable(T("Chicken Pitas"), T("images/meals/ChickenPitas.jpg"), info));
	meals.push_back(Eatable(T("Greek Salad"), T("images/meals/GreekSalad.jpg"), info));

	for(int i = 0; i < (int)meals.size(); i++) {
		meals[i].id = i;
	}

	for(deque<Eatable>::iterator eit = meals.begin(); eit != meals.end(); ++eit) {
		String xmlpath = "recipes/";
		xmlpath += eit->getName().replaceCharacter(' ', '_');
		xmlpath += ".xml";

//		std::cout << "DEBUG: Attempting to load XML data from " << xmlpath.toUTF8() << std::endl;

		try {
			recipes[eit->id] = Recipe(xmlpath);
			const vector<int>& ids = recipes[eit->id].getFoodID();
			NutritionalInfo& info = eit->getNutritionalInfo();
			int id;
			for(vector<int>::const_iterator iit = ids.begin(); iit != ids.end(); ++iit) {
				id = *iit;
				Eatable* e = foodMap[*iit];
				if(e) {
					info += e->getNutritionalInfo();
				}
			}
		} catch (...) {
			std::cerr << "Exception" << std::endl;
		}
	}

	cout << "addr: " << &recipes << endl;

	// need to loop through the recipes and populate the nutritional info here.
}
